package com.pool;


import java.util.Arrays;
import java.util.concurrent.*;

/**
 * Executors 工具类，创建线程的3大方法
 * <p>
 * 查看三大方法的底层源码，发现本质都是调用了 new ThreadPoolExecutor ( 7 大参数 )
 * <p>
 * 1. corePollSize : 核心线程数
 * 2. maximumPoolSize : 最大线程数
 * 3. keepAliveTime : 空闲的线程保留的时间数
 * 4. unit : 空闲的线程保留的时间单位
 * 5. BlockingQueue<Runnable> : 阻塞队列（阻塞队列满了会先开启最大线程数；最大线程数满之后，如果阻塞队列又满了，则会执行拒绝策略）
 * 6. ThreadFactory : 线程工厂，一般用默认的
 * 7. RejectedExecutionHandler : 队列已满，而且任务量大于最大线程的异常处理策略。
 * <p>
 * RejectedExecutionHandler的四个实现类（四种拒绝策略）
 * AbortPolicy()   抛出异常策略（丢弃任务并抛出RejectedExecutionException异常）
 * CallerRunsPolicy()   哪来的去哪里策略
 * DiscardPolicy()   丢弃策略；不会抛出异常，但是不会执行任务
 * DiscardOldestPolicy()  队列满了，就尝试和最早的任务竞争，也不会抛出异常
 * <p>
 * 详情可看：银行业务办理案例
 */
public class PoolDemo {

	public static void main(String[] args) {
//        ExecutorService threadPool = Executors.newSingleThreadExecutor();//创建单个线程
//        ExecutorService threadPool = Executors.newFixedThreadPool(5);//创建一个固定的线程池的大小
//        ExecutorService threadPool = Executors.newCachedThreadPool();//可伸缩的，遇强则强，遇弱则弱
		LinkedBlockingDeque<Runnable> objects = new LinkedBlockingDeque<>(3);

		// 调优：
		// 1、CPU密集型：几核，最大线程数就是几
		// 2、IO密集型：>
		// 程序中十分耗IO的线程

		// 自定义线程池
		ExecutorService threadPool = new ThreadPoolExecutor(
				2,
				Runtime.getRuntime().availableProcessors(),
				4,
				TimeUnit.SECONDS,
				objects,
				Executors.defaultThreadFactory(),
				new ThreadPoolExecutor.DiscardOldestPolicy()// 队列满了，执行拒绝策略
		);

		try {
			for (int i = 0; i < 9; i++) {
				// 使用线程池后，用线程池来创建线程
				int finalI = i;
				Future<Object> future = threadPool.submit(() -> {
					return null;
				});

				threadPool.execute(() -> {
					System.out.println(Thread.currentThread().getName() + " ok " + finalI);
				});
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 线程池用完之后要关闭线程池
			threadPool.shutdown();
		}
		System.out.println(Arrays.toString(args));
	}


}
